import logst.parsers_base as parsers_base
import re, sys
import pdb
from logst.helpers import *
from logst.logs_abstraction import EVENT_NOT_GROUPABLE, EVENT_HOST_GROUPABLE, EVENT_ALWAYS_GROUPABLE

class sysrqm_Parser(parsers_base.base_Parser_class):

   default_icon = "images/32px-Crystal_Clear_app_ksysguard.png"

   mem_c = re.compile("""(DMA|Normal|HighMem) free:([0-9]+)kB min:([0-9]+)kB low:([0-9]+)kB high:([0-9]+)kB active:([0-9]+)kB inactive:([0-9]+)kB present:([0-9]+)kB pages_scanned:([0-9]+) all_unreclaimable\? (.+)""")
   buf_c = re.compile("""(DMA|Normal|HighMem): ([0-9]+)\*4kB ([0-9]+)\*8kB ([0-9]+)\*16kB ([0-9]+)\*32kB ([0-9]+)\*64kB ([0-9]+)\*128kB ([0-9]+)\*256kB ([0-9]+)\*512kB ([0-9]+)\*1024kB ([0-9]+)\*2048kB ([0-9]+)\*4096kB = ([0-9]+)kB""")

   def initialize(self):

      pass

   def init_activators(self):

      self.add_regex_activator("""SysRq : Show Memory""", self.parse_line)
      self.add_regex_activator("""Normal free:""", self.sysrq_m_normal)
      self.add_regex_activator("""Normal: [0-9]""", self.sysrq_m_buffers)

   def parse_mem_dump(self, line):

      data = self.mem_c.findall(line)

      if not data:
         return None

      data = data[0]
      toret = [data[0]]

      for idx in range(1, 9):
         toret.append( int(data[idx]) )

      toret.append( data[9] )

      return toret

   def graph_mem_usage(self, line):

      data = self.mem_c.findall(line)
      if data: data = data[0]

      chart = PieChart3D(160, 100)

      chart.set_title(data[0])
 
      data = [ int(a) for a in data[1:-1] ]

      chart.add_data( data[4:7] )
      chart.add_data( [ 1000, 2000, 1000 ] )
      chart.set_pie_labels(['Active', 'Inactive', 'Present'])

      return """<img src="%s">\n""" % chart.get_url()

   def parse_line(self, log):

      # Found an SysRq+m dump!
      self.add_event(log, "SysRq+M (Memory Dump)")

      return

   def draw_all_graphs(self, event):

      out = ""

      for hostname in event.affected_hosts():

         data = self.get_variable(host = hostname, name = "Normal_memuse")

         if data:
            out += self.draw_graph(data)

      return out

   def draw_graph(self, data):

      data = [xdump[1] for xdump in data]
      xmax = max(data)

      if xmax == 0:
         return "Invalid data (%s)" % data

      data = rerange(data, 4095)

      sys.path.append("%s/pygooglechart" % self.cluster.CONFIG["libdir"])
      from pygooglechart import SimpleLineChart, Axis

      chart = SimpleLineChart(200, 125)

      chart.add_data( data )
      chart.set_axis_range(Axis.LEFT, 0, xmax )

      chart.set_title('Normal memory')
      chart.set_legend(['Free'])
      chart.set_colours(['208020', '202080'])

      return """<img src="%s">\n""" % chart.get_url()

   def sysrq_m_buffers(self, log):

      data = self.buf_c.findall(log.line)

      if not data:
         return None

      data = data[0]
      toret = []

      for item in data:
         try:    toret.append(int(item))
         except: toret.append(item)

      xlist = self.get_variable(host = log.hostname(), name = "%s_bufs" % toret[0], default = [])
      xlist.append(toret)

      self.set_variable(host = log.hostname(), name = "%s_bufs" % toret[0], value = xlist)

   def sysrq_m_normal(self, log):

      data = self.parse_mem_dump(log.message())

      if not data:
         return

      xlist = self.get_variable(host = log.hostname(), name = "%s_memuse" % data[0], default = [])
      xlist.append(data)
      self.set_variable(host = log.hostname(), name = "%s_memuse" % data[0], value = xlist)

      if len(xlist) > 1:
         event = self.add_event(log, "SysRq+M Memory Graph", long_text = self.draw_all_graphs, groupable = EVENT_HOST_GROUPABLE)

      if   data[1] <= data[2]: # normal below min
         log.add_event("System below OOM threshold!", icon = "images/32px-Crystal_Clear_app_error.png")

      elif data[1] <= data[3]: # normal below low
         log.add_event("System is under memory pressure", icon = "images/32px-Crystal_Clear_app_error.png")

      return

# kernel: SysRq : Show Memory
# kernel: Mem-info:
# kernel: DMA per-cpu:
# kernel: cpu 0 hot: low 2, high 6, batch 1
# kernel: cpu 0 cold: low 0, high 2, batch 1
# kernel: Normal per-cpu:
# kernel: cpu 0 hot: low 30, high 90, batch 15
# kernel: cpu 0 cold: low 0, high 30, batch 15
# kernel: HighMem per-cpu: empty
# kernel:
# kernel: Free pages:       33884kB (0kB HighMem)
# kernel: Active:38109 inactive:9315 dirty:16 writeback:0 unstable:0 free:8471 slab:6747 mapped:7256 pagetables:309
# kernel: DMA free:1480kB min:128kB low:256kB high:384kB active:4900kB inactive:3848kB present:16384kB pages_scanned:0 all_unreclaimable? no
# kernel: protections[]: 0 0 0
# kernel: Normal free:32404kB min:1920kB low:3840kB high:5760kB active:147536kB inactive:33412kB present:245760kB pages_scanned:0 all_unreclaimable? no
# kernel: protections[]: 0 0 0
# kernel: HighMem free:0kB min:128kB low:256kB high:384kB active:0kB inactive:0kB present:0kB pages_scanned:0 all_unreclaimable? no
# kernel: protections[]: 0 0 0
# kernel: DMA: 108*4kB 39*8kB 10*16kB 8*32kB 1*64kB 2*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 1480kB
# kernel: Normal: 1509*4kB 724*8kB 470*16kB 180*32kB 40*64kB 9*128kB 8*256kB 1*512kB 1*1024kB 0*2048kB 0*4096kB = 32404kB
# kernel: HighMem: empty
# kernel: Swap cache: add 0, delete 0, find 0/0, race 0+0
# kernel: 0 bounce buffer pages
# kernel: Free swap:       524280kB
# kernel: 65536 pages of RAM
# kernel: 0 pages of HIGHMEM
# kernel: 1600 reserved pages
# kernel: 21563 pages shared
# kernel: 0 pages swap cached
